﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
namespace YanZhiwei.DotNet2.Utilities.Common
{
    /// <summary>
    ///Image帮助类
    /// </summary>
    public static class ImageHelper
    {
        /// <summary>
        /// 图片允许的格式
        /// </summary>
        public static readonly string AllowExt = ".jpe|.jpeg|.jpg|.png|.tif|.tiff|.bmp";
        #region 将图片转换成byte[]
        /// <summary>
        /// 将图片转换成byte[]
        /// </summary>
        /// <param name="Image">Image</param>
        /// <param name="imageFormat">ImageFormat</param>
        /// <returns>byte[]</returns>
        public static byte[] ToBytes(this Image Image, ImageFormat imageFormat)
        {
            byte[] _data = null;
            using (MemoryStream ms = new MemoryStream())
            {
                using (Bitmap bitmap = new Bitmap(Image))
                {
                    bitmap.Save(ms, imageFormat);
                    ms.Position = 0;
                    _data = new byte[ms.Length];
                    ms.Read(_data, 0, Convert.ToInt32(ms.Length));
                    ms.Flush();
                }
            }
            return _data;
        }
        #endregion
        #region byte[]转换成Image
        /// <summary>
        /// byte[]转换成Image
        /// </summary>
        /// <param name="byteArray">二进制图片流</param>
        /// <returns>Image</returns>
        public static Image ToImage(byte[] byteArray)
        {
            using (MemoryStream ms = new MemoryStream(byteArray))
            {
                Image _saveImage = Image.FromStream(ms);
                ms.Flush();
                return _saveImage;
            }
        }
        #endregion 
        #region 将Bitmap转换成byte[]
        /// <summary>
        /// 将Bitmap转换成ByteArray
        /// </summary>
        /// <param name="bitmap">Bitmap</param>
        /// <param name="format">ImageFormat</param>
        /// <returns>byte[]</returns>
        public static byte[] ToBytes(this Bitmap bitmap, ImageFormat format)
        {
            MemoryStream _stream = null;
            try
            {
                _stream = new MemoryStream();
                bitmap.Save(_stream, format);
                byte[] _bytes = new Byte[_stream.Length];
                _bytes = _stream.ToArray();
                return _bytes;
            }
            finally
            {
                _stream.Close();
            }
        }
        /// <summary>
        /// 将Bitmap转换成 byte[]
        /// </summary>
        /// <param name="bitmap">Bitmap</param>
        /// <returns></returns>
        public static byte[] ToBytes(this Bitmap bitmap)
        {
            return ToBytes(bitmap, bitmap.RawFormat);
        }
        #endregion
        #region 合并图片
        /// <summary>
        /// 合并图片
        /// </summary>
        /// <param name="mergerImageWidth">合并图片的宽度</param>
        /// <param name="mergerImageHeight">合并图片的高度</param>
        /// <param name="imageX">所绘制图像的左上角的X坐标</param>
        /// <param name="imageY">所绘制图像的左上角的Y坐标</param>
        /// <param name="backgroundColor">合并图片的背景色</param>
        /// <param name="maps">所需要绘制的图片集合</param>
        /// <returns>绘制的图片</returns>
        public static Bitmap MergerImage(int mergerImageWidth, int mergerImageHeight, int imageX, int imageY, Color backgroundColor, params Bitmap[] maps)
        {
            int _imageCount = maps.Length;
            //创建要显示的图片对象,根据参数的个数设置宽度
            Bitmap _drawImage = new Bitmap(mergerImageWidth, mergerImageHeight);
            Graphics _graphics = Graphics.FromImage(_drawImage);
            try
            {
                //清除画布,背景设置为白色
                _graphics.Clear(Color.White);
                for (int j = 0; j < _imageCount; j++)
                {
                    _graphics.DrawImage(maps[j], j * imageX, imageY, maps[j].Width, maps[j].Height);
                }
            }
            finally
            {
                _graphics.Dispose();
            }
            return _drawImage;
        }
        #endregion 
        #region 调节图片亮度值
        /// <summary>
        /// 调节图片亮度值
        /// 参考：
        /// http://www.nullskull.com/faq/528/c-net--change-brightness-of-image--jpg-gif-or-bmp.aspx
        /// http://blog.csdn.net/jiangxinyu/article/details/6222302
        /// http://www.smokycogs.com/blog/image-processing-in-c-sharp-adjusting-the-brightness/
        /// </summary>
        /// <param name="Image">需要处理的图片</param>
        /// <param name="Value">亮度值【0~100，其中0表示最暗，100表示最亮】</param>
        /// <returns>调节好后的图片</returns>
        public static Bitmap AdjustBrightness(this Bitmap Image, int Value)
        {
            if (Value >= 0 && Value <= 100)
            {
                Value = 100 - Value;
                Bitmap _tempBitmap = Image;
                float _finalValue = (float)Value / 255.0f;
                Bitmap _newBitmap = new Bitmap(_tempBitmap.Width, _tempBitmap.Height);
                Graphics _newGraphics = Graphics.FromImage(_newBitmap);
                float[][] _floatColorMatrix ={
                      new float[] {1, 0, 0, 0, 0},
                      new float[] {0, 1, 0, 0, 0},
                      new float[] {0, 0, 1, 0, 0},
                      new float[] {0, 0, 0, 1, 0},
                      new float[] {_finalValue, _finalValue, _finalValue, 1, 1}
                  };
                ColorMatrix _newColorMatrix = new ColorMatrix(_floatColorMatrix);
                ImageAttributes _attributes = new ImageAttributes();
                _attributes.SetColorMatrix(_newColorMatrix);
                _newGraphics.DrawImage(_tempBitmap, new Rectangle(0, 0, _tempBitmap.Width, _tempBitmap.Height), 0, 0, _tempBitmap.Width, _tempBitmap.Height, GraphicsUnit.Pixel, _attributes);
                _attributes.Dispose();
                _newGraphics.Dispose();
                return _newBitmap;
            }
            return Image;
        }
        #endregion 
        #region 将.png,.bmp,.jpg类型图片转换成bitmap类型
        /// <summary>
        /// 将.png,.bmp,.jpg类型图片转换成bitmap类型
        /// </summary>
        /// <param name="imagePath">图片路径</param>
        /// <returns>Bitmap</returns>
        public static Bitmap ToBitmap(string imagePath)
        {
            return (Bitmap)Bitmap.FromFile(imagePath, false);
        }
        #endregion 
        #region Bitmap比较
        [DllImport("msvcrt.dll")]
        private static extern int memcmp(IntPtr b1, IntPtr b2, long count);
        /// <summary>
        /// Bitmap比较
        /// </summary>
        /// <param name="b1">Bitmap1</param>
        /// <param name="b2">Bitmap2</param>
        /// <returns>比较结果</returns>
        public static bool CompareByMemCmp(this Bitmap b1, Bitmap b2)
        {
            /*说明
             *参考链接：
             *http://stackoverflow.com/questions/2031217/what-is-the-fastest-way-i-can-compare-two-equal-size-bitmaps-to-determine-whethe
             */
            if ((b1 == null) != (b2 == null)) return false;
            if (b1.Size != b2.Size) return false;
            BitmapData _bdata1 = b1.LockBits(new Rectangle(new Point(0, 0), b1.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData _bdata2 = b2.LockBits(new Rectangle(new Point(0, 0), b2.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            try
            {
                IntPtr _bd1scan0 = _bdata1.Scan0;
                IntPtr _bd2scan0 = _bdata2.Scan0;
                int _stride = _bdata1.Stride;
                int _len = _stride * b1.Height;
                return memcmp(_bd1scan0, _bd2scan0, _len) == 0;
            }
            finally
            {
                b1.UnlockBits(_bdata1);
                b2.UnlockBits(_bdata2);
            }
        }
        /// <summary>
        /// 通过比较bitmap两者ToBase64String来判断是否相等
        /// </summary>
        /// <param name="b1">Bitmap1</param>
        /// <param name="b2">Bitmap2</param>
        /// <returns>比较结果</returns>
        public static bool CompareByBase64String(this Bitmap b1, Bitmap b2)
        {
            /*说明
            *参考链接：
            *http://blogs.msdn.com/b/domgreen/archive/2009/09/06/comparing-two-images-in-c.aspx
            */
            string _b1Base64String, _b2Base64String;
            MemoryStream _ms = new MemoryStream();
            try
            {
                b1.Save(_ms, ImageFormat.Png);
                _b1Base64String = Convert.ToBase64String(_ms.ToArray());
                _ms.Position = 0;
                b2.Save(_ms, ImageFormat.Png);
                _b2Base64String = Convert.ToBase64String(_ms.ToArray());
            }
            finally
            {
                _ms.Close();
            }
            return _b1Base64String.Equals(_b2Base64String);
        }
        /// <summary>
        /// 通过比较bitmap两者像素颜色来判断两者是否相等
        /// </summary>
        /// <param name="b1">Bitmap1</param>
        /// <param name="b2">Bitmap2</param>
        /// <returns>比较结果</returns>
        public static bool CompareByPixel(this Bitmap b1, Bitmap b2)
        {
            /*说明
             *参考链接：
             *http://blogs.msdn.com/b/domgreen/archive/2009/09/06/comparing-two-images-in-c.aspx
             */
            bool _flag = false;
            if (b1.Width == b2.Width && b1.Height == b2.Height)
            {
                _flag = true;
                Color _pixel1;
                Color _pixel2;
                for (int i = 0; i < b1.Width; i++)
                {
                    for (int j = 0; j < b1.Height; j++)
                    {
                        _pixel1 = b1.GetPixel(i, j);
                        _pixel2 = b2.GetPixel(i, j);
                        if (_pixel1 != _pixel2)
                        {
                            _flag = false;
                            break;
                        }
                    }
                }
            }
            return _flag;
        }
        /// <summary>
        /// memcmp API
        /// </summary>
        /// <param name="b1">字节数组1</param>
        /// <param name="b2">字节数组2</param>
        /// <returns>如果两个数组相同，返回0；如果数组1小于数组2，返回小于0的值；如果数组1大于数组2，返回大于0的值。</returns>
        [DllImport("msvcrt.dll")]
        private static extern IntPtr memcmp(byte[] b1, byte[] b2, IntPtr count);
        /// <summary>
        /// 通过比较bitmap两者byte[]来判断是否相等
        /// </summary>
        /// <param name="b1">Bitmap1</param>
        /// <param name="b2">Bitmap2</param>
        /// <returns>比较结果</returns>
        public static bool CompareByArray(this Bitmap b1, Bitmap b2)
        {
            /*说明
            *参考链接：
            *http://www.cnblogs.com/zgqys1980/archive/2009/07/13/1522546.html
            */
            IntPtr _result = new IntPtr(-1);
            MemoryStream _ms = new MemoryStream();
            try
            {
                b1.Save(_ms, ImageFormat.Png);
                byte[] _b1Array = _ms.ToArray();
                _ms.Position = 0;
                b2.Save(_ms, ImageFormat.Png);
                byte[] _b2Array = _ms.ToArray();
                _result = memcmp(_b1Array, _b2Array, new IntPtr(_b1Array.Length));
            }
            finally
            {
                _ms.Close();
            }
            return _result.ToInt32() == 0;
        }
        #endregion 
        #region 在图片上生成图片水印
        /// <summary>
        /// 在图片上生成图片水印
        /// </summary>
        /// <param name="imagePath">图片路径</param>
        /// <param name="waterImagePath">水印图片路径</param>
        public static void AddWaterPic(string imagePath, string waterImagePath)
        {
            Image _image = Image.FromFile(imagePath);
            Image _waterImage = Image.FromFile(waterImagePath);
            if (_image != null && _waterImage != null)
            {
                Graphics _graphics = Graphics.FromImage(_image);
                _graphics.DrawImage(_waterImage, new Rectangle(_image.Width - _waterImage.Width, _image.Height - _waterImage.Height, _waterImage.Width, _waterImage.Height), 0, 0, _waterImage.Width, _waterImage.Height, GraphicsUnit.Pixel);
                _graphics.Dispose();
                _image.Save(imagePath + ".temp");
                _image.Dispose();
                File.Delete(imagePath);
                File.Move(imagePath + ".temp", imagePath);
            }
        }
        #endregion
    }
}